package com.miyi.core;

import static spark.Spark.exception;
import static spark.Spark.get;
import static spark.Spark.halt;
import static spark.Spark.post;

import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.exception.ResourceNotFoundException;

import spark.HaltException;
import spark.route.HttpMethod;




public class App {
	private static final Object[] NULL_ARGS = new Object[0];
	
	
    public static void Route(String path,Class<? extends Controller> controllerClass){
    	get(path+"/:action", (req, res) -> {
    		req.attribute("clazz", controllerClass);
    		throw new ActionException(HttpMethod.get.name());
    	});

    	post(path+"/:action", (req, res) -> {
    		req.attribute("clazz", controllerClass);
    		throw new ActionException(HttpMethod.post.name());
    	});
    	
    	
    }
    

    
    @SuppressWarnings("unchecked")
	public static void Run(){
   	
    	exception(ActionException.class, (e, request, response) -> {
    		String currentHttpMethod = e.getMessage();
    		Class<? extends Controller> controllerClass = null;
    		Controller controller = null;
			try {
				controllerClass = (Class<? extends Controller>)request.attribute("clazz");
				controller = controllerClass.newInstance();
				controller.init(request, response);
			} catch (Exception e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
				
				halt(500, e2.getMessage());
			}
			
			boolean methodCanInvoke = true;
			boolean methodFound = false;
			Method[] methods =  controllerClass.getDeclaredMethods();

			for (Method method : methods) {
				methodCanInvoke = true;
				//System.out.println(method.getName());
				if(controller.getActionName().equals(method.getName())){
					
					if(method.isAnnotationPresent(HTTPMethod.class)){
						HTTPMethod hm = method.getAnnotation(HTTPMethod.class);
						List<String> hmList = Arrays.asList(hm.value());
						if(!hmList.contains(currentHttpMethod))methodCanInvoke=false;
					}
					
					if(methodCanInvoke){
						methodFound = true;
						try {
							method.invoke(controller, NULL_ARGS);
						} catch (InvocationTargetException ex) {
							
				            if( ex.getCause() != null){
				            	if(ex.getCause() instanceof FatalException){
					        	    response.status(HttpServletResponse.SC_OK);
					        	    response.body(((FatalException)ex.getCause()).getBody());
					        	    return;
				            	}else if(ex.getCause() instanceof ResourceNotFoundException){
					        	    response.status(HttpServletResponse.SC_OK);
					        	    response.body(((ResourceNotFoundException)ex.getCause()).getMessage());
					        	    return;
				            	}else if(ex.getCause() instanceof HaltException){
					        	    response.status(HttpServletResponse.SC_OK);
					        	    response.body(((HaltException)ex.getCause()).getBody());
					        	    return;
//				            	}else if(ex.getCause() instanceof ConnectException){
//				            		response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//					        	    response.body(((HaltException)ex.getCause()).getBody());
				            	}else if(ex.getCause() instanceof NullPointerException){
				            		ex.printStackTrace();
				            		response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
				            		response.body(((NullPointerException)ex.getCause()).toString());
					        	    return;
				            	}
				            }
				            
				            ex.printStackTrace();
					        PrintWriter writer = null;
							try {
								writer = response.raw().getWriter();
						        ex.printStackTrace(writer);
							    writer.flush();
							} catch (Exception e2) {
								response.body(ex.getMessage());
								e2.printStackTrace();
							} finally{
								if(writer!=null)
									writer.close();
							}
		            		
						} catch (Exception e1) {
							e1.printStackTrace();
					        PrintWriter writer = null;
							try {
								writer = response.raw().getWriter();
						        e1.printStackTrace(writer);
							    writer.flush();
							} catch (Exception e2) {
								response.body(e1.getMessage());
								e2.printStackTrace();
							} finally{
								if(writer!=null)
									writer.close();
							}
						}finally{
							//释放
							controller.deInit();
						}
					}
					break;
				}
			}
    		
			if(!methodFound){
	    	    response.status(HttpServletResponse.SC_NOT_FOUND);
	    	    response.body("Page not found");	
			}

    	});
    	

    }
    

}
